package com.luom.fsp.job.cycle;

import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.luom.fsp.constant.RedisConstant;
import com.luom.fsp.manager.websocket.DataWebSocketServer;
import com.luom.fsp.model.dto.other.DashboardResult;
import com.luom.fsp.model.entity.AfterSalesService;
import com.luom.fsp.model.entity.Order;
import com.luom.fsp.service.AfterSalesServiceService;
import com.luom.fsp.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 向仪表盘推送数据
 */
@Slf4j
@Component
public class DashboardData {

    @Resource
    private OrderService orderService;
    @Resource
    private AfterSalesServiceService afterSalesServiceService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Scheduled(fixedRate = 5000)
    public void pushDashboardData() {
        Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(RedisConstant.DASHBOARD_KEY);
        if (map.isEmpty()) {
            synchronizeOrders();
            map = stringRedisTemplate.opsForHash().entries(RedisConstant.DASHBOARD_KEY);
        }
        DashboardResult dashboardResult = new DashboardResult();
        dashboardResult.setAfterSales((String) map.get("afterSales"));
        dashboardResult.setPendingShipment((String) map.get("pendingShipment"));
        dashboardResult.setTodayOrders((String) map.get("todayOrders"));
        dashboardResult.setTodaySales((String) map.get("todaySales"));

        DataWebSocketServer.sendMessage(JSONUtil.toJsonStr(dashboardResult));
    }

    /**
     * 同步数据库订单数据到Redis
     */
    public void synchronizeOrders() {
        // 获取今日的开始和结束时间
        LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

        // 1. 计算今日订单数量
        QueryWrapper<Order> todayOrdersQuery = new QueryWrapper<>();
        todayOrdersQuery.ge("createTime", startOfDay)
                .lt("createTime", endOfDay);
        long todayOrders = orderService.count(todayOrdersQuery);

        // 2. 计算待发货订单数量
        QueryWrapper<Order> pendingShipmentQuery = new QueryWrapper<>();
        pendingShipmentQuery.eq("orderStatus", "paid");
        pendingShipmentQuery.eq("paymentStatus", "success");
        long pendingShipment = orderService.count(pendingShipmentQuery);

        // 3. 计算今日销售额
        QueryWrapper<Order> todaySalesQuery = new QueryWrapper<>();
        todaySalesQuery.ge("createTime", startOfDay)
                .lt("createTime", endOfDay)
                .eq("paymentStatus", "success");
        List<Order> todayOrdersList = orderService.list(todaySalesQuery);
        BigDecimal todaySales = todayOrdersList.stream()
                .map(Order::getTotalPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 4. 计算待处理售后服务请求数量
        QueryWrapper<AfterSalesService> afterSalesQuery = new QueryWrapper<>();
        afterSalesQuery.eq("serviceStatus", "pending");
        long afterSales = afterSalesServiceService.count(afterSalesQuery);

        // 将数据存储到Redis的Hash结构中
        Map<String, String> dashboardData = new HashMap<>();
        dashboardData.put("todayOrders", String.valueOf(todayOrders));
        dashboardData.put("pendingShipment", String.valueOf(pendingShipment));
        dashboardData.put("todaySales", todaySales.toString());
        dashboardData.put("afterSales", String.valueOf(afterSales));
        stringRedisTemplate.opsForHash().putAll(RedisConstant.DASHBOARD_KEY, dashboardData);
    }

    /**
     * 删除redis数据
     */
    // 每天12点删除redis数据
    @Scheduled(cron = "0 0 0 * * ?")
    public void deleteDashboardData() {
        stringRedisTemplate.delete(RedisConstant.DASHBOARD_KEY);
    }
}
